package com.example.wechathook.hook;

import static de.robv.android.xposed.XposedBridge.log;
import static de.robv.android.xposed.XposedHelpers.callMethod;
import static de.robv.android.xposed.XposedHelpers.callStaticMethod;
import static de.robv.android.xposed.XposedHelpers.findAndHookConstructor;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.findClass;

import java.util.Map;

import android.database.Cursor;
import android.text.TextUtils;

import com.example.wechathook.util.WechatMainDBHelper;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

/***
 * 
 * 微信消息防撤回
 * 
 * @author chencq
 *
 */
public class MessageUnRecalledHook extends BaseHook {

	private ClassLoader classLoader;
	private WechatMainDBHelper mDb;

	@Override
	public void hook(XC_LoadPackage.LoadPackageParam lpp) {
		classLoader = lpp.classLoader;

		findAndHookMethod("com.tencent.mm.sdk.platformtools.r", classLoader, "N", String.class, String.class,
				String.class, new XC_MethodHook() {
					@Override
					protected void afterHookedMethod(MethodHookParam param) throws Throwable {
						String xml = (String) param.args[0];
						String tag = (String) param.args[1];
						if (TextUtils.isEmpty(xml) || TextUtils.isEmpty(tag) || !tag.equals("sysmsg")
								|| !xml.contains("revokemsg")) {
							return;
						}

						@SuppressWarnings("unchecked")
						Map<String, String> map = (Map<String, String>) param.getResult();
						if (map == null)
							return;

						String key = ".sysmsg.$type";
						if (!map.containsKey(key))
							return;

						String type = map.get(key);
						if (type == null || !type.equals("revokemsg"))
							return;

						final String talker = map.get(".sysmsg.revokemsg.session");
						String replacemsg = map.get(".sysmsg.revokemsg.replacemsg");
						String msgsvrid = map.get(".sysmsg.revokemsg.newmsgid");

						if (replacemsg.startsWith("你") || replacemsg.toLowerCase().startsWith("you")) {
							return;
						}

						String[] strings = replacemsg.split("\"");
						replacemsg = "\"" + strings[1] + "\" " + "尝试撤回上一条消息 （已阻止)";

						map.put(key, null);
						param.setResult(map);

						try {
							Cursor cursor = mDb.getMessageBySvrId(msgsvrid);
							if (cursor == null || !cursor.moveToFirst())
								return;

							int t = cursor.getInt(cursor.getColumnIndex("type"));
							String content;
							switch (t) {
							case 1:// 文本
								content = cursor.getString(cursor.getColumnIndex("content")).trim();
								if (talker.contains("@chatroom")) {
									int idx = content.indexOf(":");
									if (idx != -1) {
										content = content.substring(idx + 1, content.length()).trim();
									}
								}
								if (!TextUtils.isEmpty(content)) {
									replacemsg += ": " + content;
								}
								break;
							case 3:// 图片
								String imgPath = cursor.getString(cursor.getColumnIndex("imgPath"));
								if (!TextUtils.isEmpty(imgPath)) {

								}
								break;
							case 34:// 语音

								break;
							case 43:// 小视频

								break;
							case 47:// emoji

								break;
							default:
								break;
							}

							long createTime = cursor.getLong(cursor.getColumnIndex("createTime"));
							int idx = cursor.getColumnIndex("talkerId");
							int talkerId = -1;
							if (idx != -1) {
								talkerId = cursor.getInt(cursor.getColumnIndex("talkerId"));
							}

							cursor.close();
							mDb.insertSystemMessage(talker, talkerId, replacemsg, createTime + 1);

							Class ah = findClass("com.tencent.mm.model.ah", classLoader);
							callMethod(callMethod(callStaticMethod(ah, "tu"), "rj"), "bbz");

						} catch (Throwable t) {
							log(t);
						}
					}
				});

		findAndHookConstructor("com.tencent.mm.storage.h", classLoader, "com.tencent.mm.bb.g", new XC_MethodHook() {
			@Override
			protected void afterHookedMethod(MethodHookParam param) throws Throwable {
				Object db = param.args[0];
				if (mDb == null) {
					try {
						mDb = new WechatMainDBHelper(db);
					} catch (Throwable t) {
						log(t);
					}
				}
			}
		});
	}
}
